
package com.hlkj.pay.app.merchant.ext.impl.yytpay.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.YytPayScenePayOrderExtPt;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.constant.YytPayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.constant.YytPayExtConstant;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.dto.YytPayConfig;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.dto.resp.YytOrderNativeResp;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.dto.resp.YytOrderResp;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.handler.YytPayCommonParamsHandle;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.infrastructure.model.common.CommonAppDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.service.common.ICommonAppConfigService;
import com.hlkj.pay.util.WeChatOAuthUtils;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 公众号统一下单
 *
 * @author HlpayTeam
 * @date 2024/11/18 13:07
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = YytPayExtConstant.NATIVE_PAY)
public class YytPayNativePayOrderExtPt extends YytPaySceneCommonPayOrder implements YytPayScenePayOrderExtPt {

    @Value("${hlkj.wxJsApi}")
    private String wxJsApi;

    private final YytPayCommonParamsHandle yytPayCommonParamsHandle;

    private final ICommonAppConfigService commonAppConfigService;

    @Override
    public void submitChannelPayOrder(ChannelPayOrderContext channelPayOrderContext) {

        log.info("银盈通 NATIVE 请求参数:{}", JsonUtils.toJsonString(channelPayOrderContext));
        CommonResult<YytPayConfig> lyytPayConfigCommonResult = yytPayCommonParamsHandle.yytPayConfig(channelPayOrderContext.getProviderChannelConfigDO(),
                channelPayOrderContext.isTest());
        if (!lyytPayConfigCommonResult.isSuccess()) {
            channelPayOrderContext.setRemark(lyytPayConfigCommonResult.getMsg());
            channelPayOrderContext.setProcessStatus(false);
            return;
        }
        // 支付订单信息
        PayOrderDO payOrderDO = channelPayOrderContext.getPayOrderDO();
        // 支付方式信息
        PayWayDO payWayDO = channelPayOrderContext.getPayWayDO();
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = channelPayOrderContext.getMerchantAppChannelDO();
        // 银盈通配置信息
        YytPayConfig yytPayConfig = lyytPayConfigCommonResult.getData();
        // 支付方式
        PayEnums.PAY_TYPE payType =  PayEnums.PAY_TYPE.fromByCode(payWayDO.getType());
        try {
            YytPayAppChannelParams yytAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YytPayAppChannelParams.class);

            String payway = yytPayCommonParamsHandle.getPayWay(payWayDO);
            if(StrUtil.isEmpty(payway)){
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelPayOrderContext.setRemark("银盈通提交 NATIVE支付 支付类型: "+payWayDO.getType()+" 不支持");
                return;
            }

            if (!StringUtils.hasText(payOrderDO.getAuthCode())) {
                String payUrl = wxJsApi + "?payOrderNo=" + payOrderDO.getPayOrderNo();
                channelPayOrderContext.setPayInfo(payUrl);
                channelPayOrderContext.setPayDataType("pay_url");
                channelPayOrderContext.setRequestThird(false);
                return;
            }

            ProviderChannelConfigDO providerChannelConfigDO = channelPayOrderContext.getProviderChannelConfigDO();
            CommonAppDO commonAppDO = commonAppConfigService.detail(providerChannelConfigDO.getWechatDefaultPubId());
            if (commonAppDO == null) {
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelPayOrderContext.setRemark("银盈通微信扫码支付失败，未配置appid");
                return;
            }
            CommonResult<String> auth = WeChatOAuthUtils.getOpenId(commonAppDO.getAppId(), commonAppDO.getAppSecret(), payOrderDO.getAuthCode());
            if (!auth.isSuccess()) {
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelPayOrderContext.setRemark("银盈通微信扫码支付失败，" + auth.getMsg());
                return;
            }

            // 支付接口
            Map<String,Object> reqData = new HashMap<>();
            reqData.put("merchant_number",yytAppChannelParams.getMchId());
            reqData.put("order_number", payOrderDO.getPayOrderNo());
            reqData.put("notify_url", channelPayOrderContext.getNotifyUrl());
            reqData.put("good_desc", payOrderDO.getSubject());
            reqData.put("total_amount", NumberUtil.roundStr(payOrderDO.getAmount().doubleValue(),2));
            reqData.put("pay_type", payway);
            reqData.put("biz_id", auth.getData());
            reqData.put("client_ip", payOrderDO.getClientIp());
            reqData.put("interface_type", "02");
            reqData.put("sub_appid",commonAppDO.getAppId());
            reqData.put("channel_merch_no",yytPayCommonParamsHandle.getMchAtId(merchantAppChannelDO.getSubMchId(),payType));

            log.info("银盈通提交NATIVE支付 支付请求参数:{}", JSONUtil.toJsonStr(reqData));
            YytOrderResp result = yytPayCommonParamsHandle.sendPostRequest("https://gc-gw.gomepay.com/gpayCashApi", JSONUtil.toJsonStr(reqData), "cash-api@gcash.trade.qrcode.pay",yytPayConfig,payOrderDO,"4",payway);
            log.info("银盈通提交NATIVE支付 支付返回参数:{}", JSONUtil.toJsonStr(result));
            if(result == null ||!"900888".equals(result.getCode())) {
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelPayOrderContext.setRemark(result.getMsg());
                return;
            }
            // 结果转对象
            YytOrderNativeResp NATIVEPayRes = JSONUtil.toBean(result.getData(), YytOrderNativeResp.class);
            // 通信状态和支付状态都成功
            channelPayOrderContext.setInsOrderNo(NATIVEPayRes.getOrder_id());
            channelPayOrderContext.setChannelOrderNo(NATIVEPayRes.getBank_order_id());

            channelPayOrderContext.setPayDataType("data");
            channelPayOrderContext.setPayInfo(NATIVEPayRes.getPay_data());
        }catch (Exception e) {
            log.error("银盈通提交NATIVE支付 请求失败, error: {}",e);
            channelPayOrderContext.setRemark("银盈通提交NATIVE支付 请求失败, error: " + e.getMessage());
            channelPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    @Override
    public void queryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void closeChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonCloseChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void queryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelClosePayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void refundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public void queryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonQueryRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public boolean refundApply(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        return true;
    }

    @Override
    public CommonResult<String> channelOrderCode(ChannelPayOrderContext channelPayOrderContext) {
        return CommonResult.success();
    }
}
